home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr05 / xnot12a.zip / BUFFER.C < prev    next >
C/C++ Source or Header  |  1993-06-11  |  23KB  |  1,035 lines

  1. #include "jam.h"
  2.  
  3. /*
  4.  *        Buffer handling.
  5.  */
  6. #include "stdlib.h"
  7. #include "def.h"
  8. #include "keyname.h"
  9. #include "kbd.h"            /* needed for modes */
  10.  
  11. #ifdef FAT
  12. # include "io.h"
  13. #endif
  14.  
  15. static BUFFER rn_(*makelist,(void));
  16. static RSIZE rn_(itor,(char *buf, int width, RSIZE num));
  17. static int rn_(_tobuffer,(int f, int n, BOOL newwindow));
  18.  
  19. /* JAM  - made most strings static so defined at most 1 time
  20.  */
  21. static char *switchto = "Switch to buffer: ";
  22. static char *switchtod = "Switch to buffer: (default %s) ";
  23. static char *switchtob = "Switch to buffer in other window: ";
  24. static char *switchtobd = "Switch to buffer in other window: (default %s) ";
  25. static char *insertbd = "Insert buffer: (default %s) ";
  26. static char *insertb = "Insert buffer: ";
  27. static char *notself = "Cannot insert buffer into self";
  28. static char *killb = "Kill buffer: (default %s) ";
  29. static char *only1 = "No other buffers.";
  30. static char *blist = "*Buffer List*";
  31. static char *mrbuffer = " MR Buffer";
  32. static char *sizefile = "Size       File";
  33. static char *savefile = "Save file ";
  34. static char *nosave = "(No files need saving)";
  35. static char *killanyway = "Buffer modified; kill anyway";
  36. static char *notonname = "Cursor not on valid buffer name.";
  37. static char *notonword = "Cursor not on word.";
  38.  
  39. /*
  40.  * Attach a buffer to a window. The values of dot and mark come
  41.  * from the buffer if the use count is 0. Otherwise, they come
  42.  * from some other window.  *scratch* is the default alternate
  43.  * buffer.
  44.  */
  45. /*ARGSUSED*/
  46. usebuffer(f, n)
  47. int f, n;
  48. {
  49.   return (_tobuffer(f, n, FALSE));
  50. }
  51.  
  52. /*
  53.  * pop to buffer asked for by the user.
  54.  */
  55. /*ARGSUSED*/
  56. poptobuffer(f, n)
  57. int f, n;
  58. {  
  59.   return (_tobuffer(f, n, TRUE));
  60. }
  61. /* work function for usebuffer and popbuffer - split by
  62. * me to shrink the code base, and add confusion! :)   JAM
  63. */
  64. static int _tobuffer(f, n, newwindow)
  65. int f;
  66. int n;
  67. BOOL newwindow;
  68. {
  69.   register BUFFER *bp, *scratch;
  70.   register EWINDOW *wp;
  71.   register int    s;
  72.   char    bufn[NBUFN];
  73.  
  74.   /* check for NULL alt buffer
  75.   */
  76.   if (curbp->b_altb == NULL)
  77.     curbp->b_altb = curbp->b_bufp;
  78.   if ((curbp->b_altb == NULL) && (bheadp != curbp))
  79.     curbp->b_altb = bheadp;
  80.   if (curbp->b_altb == NULL)
  81.     {
  82.       if (!(scratch = bfind(Scratch, TRUE)))
  83.         scratch = bheadp;
  84.       curbp->b_altb = scratch;    /* use scratch as last resort */
  85.     }
  86.  
  87.   /* Get buffer to use from user  - check for
  88.    * no alt buff or in scratch and altb is same, no default
  89.   */
  90.   if ((curbp->b_altb == NULL) || (curbp == scratch))
  91.     s=eread(switchto, bufn, NBUFN, EFNEW|EFBUF);
  92.   else
  93.     s=eread(switchtod, bufn, NBUFN,EFNEW|EFBUF, curbp->b_altb->b_bname);
  94.   
  95.   if (s == ABORT) 
  96.     return s;
  97.   if ((s == FALSE) && (curbp->b_altb != NULL))
  98.     bp = curbp->b_altb;
  99.   else if ((bp=bfind(bufn, TRUE)) == NULL) 
  100.     return FALSE;
  101.   
  102.   if (!newwindow)  
  103.     {
  104.     /* and put it in current window 
  105.     */
  106.     if (showbuffer(bp, curwp, WFMODE|WFFORCE|WFHARD) != TRUE)
  107.       return (FALSE);
  108.     curbp = bp;
  109.     thisflag |= CFNEWB;
  110.     return (TRUE);
  111.     }
  112.   else
  113.     {
  114.     /* and put it in a new window 
  115.      */
  116.     if ((wp = popbuf(bp)) == NULL) 
  117.       return FALSE;
  118.     curbp = bp;
  119.     curwp = wp;
  120.     thisflag |= CFNEWB;
  121.     return TRUE;
  122.     }
  123. }
  124. /*
  125.  * Dispose of a buffer, by name.
  126.  * Ask for the name. Look it up (don't get too
  127.  * upset if it isn't there at all!). Clear the buffer (ask
  128.  * if the buffer has been changed). Then free the header
  129.  * line and the buffer header. Bound to "C-X K".
  130.  */
  131. /*ARGSUSED*/
  132. killbuffer(f, n)
  133. int f, n;
  134. {
  135.   register BUFFER *bp;
  136.   register int    s;
  137.   char bufn[NBUFN];
  138.  
  139.   if ((s=eread(killb, bufn, NBUFN, EFNEW|EFBUF, curbp->b_bname)) == ABORT) 
  140.     return (s);
  141.   else if (s == FALSE) 
  142.     bp = curbp;
  143.   else if ((bp=bfind(bufn, FALSE)) == (BUFFER *)0) 
  144.     return FALSE;
  145.   return (nukebuffer(bp));
  146. }
  147.  
  148. /* Guts of killbuffer split out so internal functions
  149. * can kill buffers when they want to (JAM)
  150. */
  151. int nukebuffer(bp)
  152. BUFFER *bp;
  153. {
  154.   EWINDOW *wp;
  155.   register BUFFER *bp1, *bp2;
  156.  
  157.   /* Find some other buffer to display. Try the alternate buffer,
  158.   * then the first different buffer in the buffer list.    If
  159.   * there's only one buffer, create buffer *scratch* and make
  160.   * it the alternate buffer.  Return if *scratch* is only buffer.
  161.   */
  162.   if ((bp1 = bp->b_altb) == NULL) 
  163.     {
  164.       bp1 = (bp == bheadp) ? bp->b_bufp : bheadp;
  165.       if (bp1 == NULL) 
  166.         {
  167.           /* Only one buffer; see if it's scratch
  168.           * else create scratch as replacement/alternate
  169.           */
  170.           if (bp == bfind(Scratch, FALSE))
  171.             {
  172.               ewprintf(only1);
  173.               return FALSE;
  174.             }
  175.           if ((bp1 = bfind(Scratch, TRUE)) == NULL)
  176.             return FALSE;
  177.         }
  178.     }
  179.  
  180.   /* clear it; user can refuse if modified and if so,
  181.   * just abort and go home happy
  182.   */
  183.   if (bclear(bp) != TRUE) 
  184.     return TRUE;
  185.  
  186.   /* Unhook it from any windows
  187.   */
  188.   for (wp = wheadp; bp->b_nwnd > 0; wp = wp->w_wndp) 
  189.     {
  190.       if (wp->w_bufp == bp) 
  191.         {
  192.           bp2 = bp1->b_altb;        /* save alternate buffer */
  193.           if (showbuffer(bp1, wp, WFMODE|WFFORCE|WFHARD))
  194.             bp1->b_altb = bp2;
  195.           else
  196.             bp1 = bp2;            /* gack! */
  197.         }
  198.     }
  199.  
  200. #ifdef WINDOWED
  201.   WindowSleepCursor();
  202. #endif
  203.  
  204.   /* Free it now; redirect any b_altb/b_bufp pointers from 
  205.   * doomed buffer and unlink doomed buffer from chain.
  206.   */
  207.   if (bp == curbp)
  208.     curbp = bp1;
  209.   free((char *) bp->b_linep);        /* Release header line. */
  210.   bp2 = NULL;                /* Find the header.    */
  211.   bp1 = bheadp;
  212.   while (bp1 != bp) 
  213.     {
  214.       if (bp1->b_altb == bp)
  215.         bp1->b_altb = ((bp->b_altb == bp1) ? NULL : bp->b_altb);
  216.       bp2 = bp1;
  217.       bp1 = bp1->b_bufp;
  218.     }
  219.   bp1 = bp1->b_bufp;            /* Next one in chain.    */
  220.   if (bp2 == NULL)            /* Unlink it.        */
  221.     bheadp = bp1;
  222.   else
  223.     bp2->b_bufp = bp1;
  224.  
  225.   /* Finish with altb's    
  226.   */  
  227.   while (bp1 != NULL) 
  228.     {
  229.       if (bp1->b_altb == bp)
  230.         bp1->b_altb = (bp->b_altb == bp1) ? NULL : bp->b_altb;
  231.       bp1 = bp1->b_bufp;
  232.     }
  233.   free(bp->b_bname);            /* Release name block    */
  234.  
  235.   if (bp->b_iname[0] && fileisok(bp->b_iname))
  236.     {
  237.       unlink(bp->b_iname);        /* Delete incremental save file */
  238.       MakeIncSaveLog();            /* update crash file log */
  239.     }
  240.  
  241.   clearUndo(bp);
  242.  
  243.   if (bp->b_flag & BFDELETE)
  244.     unlink(bp->b_fname);
  245.  
  246.   free((char *) bp);            /* Release buffer block */
  247.  
  248. #ifdef WINDOWED
  249.   WindowNormalCursor();
  250. #endif
  251.  
  252.   thisflag |= CFKILLB;
  253.   return TRUE;
  254. }
  255.  
  256. /*
  257.  * Save some buffers - just call anycb with the arg flag.
  258.  */
  259. /*ARGSUSED*/
  260. savebuffers(f, n)
  261. int f, n;
  262. {
  263.   if (anycb(f) == ABORT) 
  264.     return ABORT;
  265.   return TRUE;
  266. }
  267.  
  268. /*
  269.  * Display the buffer list. This is done
  270.  * in two parts. The "makelist" routine figures out
  271.  * the text, and puts it in a buffer. "popbuf"
  272.  * then pops the data onto the screen. Bound to
  273.  * "C-X C-B".
  274.  */
  275. /*ARGSUSED*/
  276. listbuffers(f, n)
  277. int f, n;
  278. {
  279.   register BUFFER *bp;
  280.   register EWINDOW *wp;
  281.   
  282.   if ((bp=makelist()) == NULL || (wp=popbuf(bp)) == NULL)
  283.     return FALSE;
  284.   wp->w_dotp = bp->b_dotp;    /* fix up if window already on screen */
  285.   wp->w_doto = bp->b_doto;
  286.   thisflag = 0;
  287.  
  288.   for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
  289.     if (wp->w_bufp == bp) 
  290.       wp->w_flag |= WFHARD|WFFORCE;
  291.  
  292.   return TRUE;
  293. }
  294.  
  295. /*
  296.  * This routine rebuilds the text for the
  297.  * list buffers command. Return TRUE if
  298.  * everything works. Return FALSE if there
  299.  * is an error (if there is no memory).
  300.  */
  301. static BUFFER *makelist() 
  302. {
  303.   register char    *cp1;
  304.   register char    *cp2;
  305.   register char    c;
  306.   register BUFFER *bp;
  307.   LINE        *lp;
  308.   register RSIZE    nbytes;
  309.   BUFFER        *blp;
  310. #define SIZENUM 10
  311. #define LINENUM 200
  312. #define BUFNAMELEN  NBUFN 
  313.   char        b[SIZENUM+1];
  314.   char        line[LINENUM];
  315.  
  316.  
  317.   if ((blp = bfind(blist, TRUE)) == NULL) 
  318.     return NULL;
  319.  
  320.   blp->b_flag &= ~(BFVIEW | BFCHG);
  321.   if (bclear(blp) != TRUE)
  322.     return NULL;
  323.  
  324.   (VOID) strcpy(line, mrbuffer);
  325.   cp1 = line + 10;
  326.   while(cp1 < line + 4 + BUFNAMELEN + 1) 
  327.     *cp1++ = ' ';
  328.   
  329.   (VOID) strcpy(cp1, sizefile);
  330.   if (addline(blp, line) == NULL) 
  331.     return NULL;
  332.   (VOID) strcpy(line, " -- ------");
  333.   cp1 = line + 10;
  334.   
  335.   while(cp1 < line + 4 + BUFNAMELEN+ 1) 
  336.     *cp1++ = ' ';
  337.   
  338.   (VOID) strcpy(cp1, "----       ----");
  339.   if (addline(blp, line) == NULL) 
  340.     return NULL;
  341.   
  342.   bp = bheadp;                /* For all buffers    */
  343.   while (bp != NULL) 
  344.     {
  345.       BOOL touched = FALSE;
  346.       LINE *addedline;
  347.  
  348.       cp1 = line;            /* Start at left edge    */
  349.       *cp1++ = (char)((bp == curbp) ? '>' : ' ');
  350.       *cp1++ = (char)(((bp->b_flag&BFCHG) != 0) ? '*' : 
  351.                        (bp->b_flag&BFVIEW) ? '%' : ' ');
  352.       *cp1++ = (char)' ';            /* Gap.            */
  353.       *cp1++ = (char)' ';
  354.       cp2 = &bp->b_bname[0];        /* Buffer name        */
  355.       while ((c = *cp2++) != 0)
  356.     *cp1++ = c;
  357.       while (cp1 < &line[4+BUFNAMELEN+1])
  358.     *cp1++ = ' ';
  359.       nbytes = 0;            /* Count bytes in buf.    */
  360.       if (bp != blp) 
  361.     {
  362.       lp = lforw(bp->b_linep);
  363.       while (lp != bp->b_linep) 
  364.         {
  365.               if (lp->l_flag & LFCHANGE)
  366.                 touched = TRUE;
  367.           nbytes += llength(lp)+1;
  368.           lp = lforw(lp);
  369.         }
  370.       if(nbytes) 
  371.             nbytes--;    /* no bonus newline    */
  372.     }
  373.       (VOID) itor(b, SIZENUM, nbytes);    /* 10 digit buffer size. */
  374.       cp2 = &b[0];
  375.       while ((c = *cp2++) != 0)
  376.     *cp1++ = c;
  377.       *cp1++ = ' ';            /* Gap..        */
  378.       cp2 = &bp->b_fname[0];        /* File name        */
  379.     if (*cp2 != 0) 
  380.       {
  381.     while ((c = *cp2++) != 0) 
  382.       {
  383.         if (cp1 < &line[LINENUM-1])
  384.           *cp1++ = c;
  385.       }
  386.       }
  387.       *cp1 = 0;            /* Add to the buffer.    */
  388.       if ((addedline = addline(blp, line)) == NULL)
  389.     return NULL;
  390.       if (touched)
  391.         changelineflag(addedline, TRUE);
  392.       bp = bp->b_bufp;
  393.     }
  394.   blp->b_dotp = lforw(blp->b_linep);    /* put dot at beginning of buffer */
  395.   blp->b_doto = 0;
  396.  
  397.   blp->b_flag |= BFVIEW;
  398.  
  399.   if((blp->b_modes[0] = name_mode(BlistStr)) == NULL) 
  400.     {
  401.       blp->b_modes[0] = &map_table[0];
  402.       ewprintf("Can't set mode: %s", BlistStr);
  403.     }
  404.   return blp;                /* All done        */
  405. }
  406.  
  407. /*
  408.  * Used above.
  409.  */
  410. static RSIZE itor(buf, width, num)
  411. register char buf[]; 
  412. register int width; 
  413. register RSIZE num; 
  414. {
  415.   register RSIZE r;
  416.   
  417.   if (num / 10 == 0) 
  418.     {
  419.       buf[0] = (char)((num % 10) + '0');
  420.       for (r = 1; r < width; buf[r++] = ' ')
  421.     ;
  422.       buf[width] = '\0';
  423.       return 1;
  424.     } 
  425.   else 
  426.     {
  427.       buf[r = itor(buf, width, num / (RSIZE)10)] =
  428.     (char)((num % (RSIZE)10) + '0');
  429.       return r + 1;
  430.     }
  431.   /*NOTREACHED*/
  432. }
  433.  
  434. /*
  435.  * The argument "text" points to
  436.  * a string. Append this line to the
  437.  * buffer. Handcraft the EOL
  438.  * on the end. Return TRUE if it worked and
  439.  * FALSE if you ran out of room.
  440.  *
  441.  * CAVEAT - this code will NOT mark added lines as LFCHANGE'd
  442.  *
  443.  */
  444. LINE *addline(bp, text) 
  445. register BUFFER *bp; 
  446. char *text; 
  447. {
  448.   register LINE    *lp;
  449.   register int    i;
  450.   register int    ntext;
  451.   
  452.   if (bp->b_flag & BFVIEW)
  453.     {
  454.       ttbeep();
  455.       return NULL;
  456.     }
  457.  
  458.   if (filetimechanged(bp))
  459.     return(FALSE);
  460.  
  461.   clearUndo(bp);
  462.  
  463.   ntext = strlen(text);
  464.   if ((lp=lalloc(ntext)) == NULL)
  465.     return NULL;
  466.   for (i=0; i<ntext; ++i)
  467.     lputc(lp, i, text[i]);
  468.   bp->b_linep->l_bp->l_fp = lp;        /* Hook onto the end    */
  469.   lp->l_bp = bp->b_linep->l_bp;
  470.   bp->b_linep->l_bp = lp;
  471.   lp->l_fp = bp->b_linep;
  472. #ifdef CANTHAPPEN
  473.   if (bp->b_dotp == bp->b_linep)        /* If "." is at the end    */
  474.     bp->b_dotp = lp;                        /* move it to new line    */
  475.   if (bp->b_markp == bp->b_linep)        /* ditto for mark    */
  476.     bp->b_markp = lp;
  477. #endif
  478.   return lp;
  479. }
  480.  
  481. /*
  482.  * Look through the list of buffers, giving the user
  483.  * a chance to save them.  Return TRUE if there are
  484.  * any changed buffers afterwards. Buffers that don't
  485.  * have an associated file don't count. Return FALSE
  486.  * if there are no changed buffers.
  487.  */
  488. anycb(f)
  489. int f; 
  490. {
  491.   register BUFFER *bp;
  492.   register int    s = FALSE, save = FALSE;
  493.   char prompt[NFILEN + 11];
  494.   
  495.   for (bp = bheadp; bp != NULL; bp = bp->b_bufp) 
  496.     {
  497.       if ((bp->b_fname[0] != '\0') && (bp->b_flag&BFCHG))
  498.     {
  499.           if (f == ABORT)    /* Just care to find if 1 file */
  500.             {                   /* is changed (JAM)            */
  501.               s = TRUE;
  502.               break;
  503.             }
  504.       strcpy(prompt, savefile);
  505.       strcpy(prompt + 10, bp->b_fname);
  506.  
  507.           if ((f == TRUE) || ((save = eyorn(prompt)) == TRUE)
  508.           && (buffsave(bp) == TRUE))
  509.         bp->b_flag &= ~BFCHG;
  510.       else 
  511.             s = TRUE;
  512.       if (save == ABORT) 
  513.         return (save);
  514.       save = TRUE;
  515.     }
  516.     }
  517.   if (save == FALSE)
  518.     ewprintf(nosave);
  519.   return s;
  520. }
  521.  
  522. /*
  523.  * Search for a buffer, by name.
  524.  * If not found, and the "cflag" is TRUE,
  525.  * create a buffer and put it in the list of
  526.  * all buffers. Return pointer to the BUFFER
  527.  * block for the buffer.
  528.  */
  529. BUFFER    *bfind(bname, cflag) 
  530. register char *bname; 
  531. int cflag;
  532. {
  533.   register BUFFER *bp;
  534.   register LINE    *lp;
  535.   int i;
  536.   extern int defb_nmodes;
  537.   extern MAPS *defb_modes[PBMODES];
  538.   extern char defb_flag;
  539.   
  540.   bp = bheadp;
  541.   for (bp = bheadp; bp; bp = bp->b_bufp)
  542.     {
  543.       if (strcmp(bname, bp->b_bname) == 0)
  544.     return bp;
  545.     }
  546.   if (cflag!=TRUE) 
  547.     return NULL;
  548.   
  549.   /*NOSTRICT*/
  550.   if (!(bp=(BUFFER *)calloc(1, sizeof(BUFFER))))
  551.     {
  552.       ewprintf(Nobytes, sizeof(BUFFER));
  553.       return NULL;
  554.     }
  555.  
  556.   if ((bp->b_bname=malloc((unsigned)(strlen(bname)+1))) == NULL) 
  557.     {
  558.       ewprintf(Nobytes, strlen(bname)+1);
  559.       free((char *) bp);
  560.       return NULL;
  561.     }
  562.  
  563.   if ((lp = lalloc(0)) == NULL) 
  564.     {
  565.       free(bp->b_bname);
  566.       free((char *) bp);
  567.       return NULL;
  568.     }
  569.   bp->b_altb = bp->b_bufp = NULL;
  570.   bp->b_dotp  = lp;
  571.   bp->b_flag  = defb_flag;
  572.   bp->b_linep = lp;
  573.   bp->b_nmodes = defb_nmodes;
  574.   
  575.   i = 0;
  576.   do 
  577.     {
  578.       bp->b_modes[i] = defb_modes[i];
  579.     } while(i++ < defb_nmodes);
  580.  
  581.   (VOID) strcpy(bp->b_bname, bname);
  582.   lforw(lp) = lp;
  583.   lback(lp) = lp;
  584.   bp->b_bufp = bheadp;
  585.   bheadp = bp;
  586.   return bp;
  587. }
  588.  
  589. /*
  590.  * This routine blows away all of the text
  591.  * in a buffer. If the buffer is marked as changed
  592.  * then we ask if it is ok to blow it away; this is
  593.  * to save the user the grief of losing text. The
  594.  * window chain is nearly always wrong if this gets
  595.  * called; the caller must arrange for the updates
  596.  * that are required. Return TRUE if everything
  597.  * looks good.
  598.  */
  599. bclear(bp) 
  600. register BUFFER *bp; 
  601. {
  602.   register LINE    *lp;
  603.   register int    s;
  604.   VOID        lfree();
  605.   
  606.   if ((bp->b_flag&BFCHG) && (s=eyesno(killanyway)) != TRUE)
  607.     return (s);
  608.  
  609. #ifdef WINDOWED
  610.   WindowSleepCursor();
  611. #endif
  612.  
  613.   bp->b_flag  &= ~BFCHG;            /* Not changed        */
  614.   while ((lp=lforw(bp->b_linep)) != bp->b_linep)
  615.     lfree(lp);
  616.   bp->b_dotp  = bp->b_linep;        /* Fix "."        */
  617.   bp->b_dotp->l_flag = 0;
  618.   bp->b_doto  = 0;
  619.   bp->b_markp = NULL;            /* Invalidate "mark"    */
  620.   bp->b_marko = 0;
  621.   bp->b_time = 0;
  622.   bp->b_flag &= ~(BFINC | BFVIEW | BFDIR | BFSAVED);
  623.   clearUndo(bp);
  624.  
  625. #ifdef WINDOWED
  626.   WindowNormalCursor();
  627. #endif
  628.   return TRUE;
  629. }
  630.  
  631. /*
  632.  * Display the given buffer in the given window. Flags indicated
  633.  * action on redisplay.
  634.  */
  635. showbuffer(bp, wp, flags) 
  636. register BUFFER *bp; 
  637. register EWINDOW *wp; 
  638. int flags;
  639. {
  640.   register BUFFER *obp;
  641.  
  642.   if (wp->w_bufp == bp)             /* Easy case!    */
  643.     {
  644.       wp->w_flag |= flags;
  645.       return TRUE;
  646.     }
  647.   
  648.   /* First, dettach the old buffer from the window 
  649.    */
  650.   obp = wp->w_bufp;
  651.   if (obp != NULL)     /* null if new window only */
  652.     {
  653.       obp->b_nwnd--;
  654.       obp->b_dotp  = wp->w_dotp;
  655.       obp->b_doto  = wp->w_doto;
  656.       obp->b_markp = wp->w_markp;
  657.       obp->b_marko = wp->w_marko;
  658.     }
  659.   
  660.   /* Now, attach the new buffer to the window 
  661.   */
  662.   wp->w_bufp = bp;
  663.   wp->w_dotp  = bp->b_dotp;
  664.   wp->w_doto  = bp->b_doto;
  665.   wp->w_markp = bp->b_markp;
  666.   wp->w_marko = bp->b_marko;
  667.  
  668.   bp->b_altb = obp;        /* remember any alt window */
  669.   bp->b_nwnd++;            /* add one to visible windows */
  670.   wp->w_flag |= WFMODE|flags;
  671.   return TRUE;
  672. }
  673.  
  674. /*
  675.  * Pop the buffer we got passed onto the screen.
  676.  * Returns a status.
  677.  */
  678. EWINDOW *popbuf(bp) 
  679. register BUFFER *bp; 
  680. {
  681.   register EWINDOW *wp;
  682.   
  683.   if (bp->b_nwnd == 0)         /* Not on screen yet.    */
  684.     {
  685.       if ((wp=wpopup()) == NULL) 
  686.     return NULL;
  687.     } 
  688.   else
  689.     for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
  690.       if (wp->w_bufp == bp) 
  691.     {
  692.       wp->w_flag |= (WFHARD|WFFORCE);
  693.       return wp ;
  694.     }
  695.   if (showbuffer(bp, wp, WFHARD) != TRUE) 
  696.     return NULL;
  697.   return wp;
  698. }
  699.  
  700. /*
  701.  * Insert another buffer at dot.  Very useful.
  702.  */
  703. /*ARGSUSED*/
  704. bufferinsert(f, n)
  705. int f, n;
  706. {
  707.   register BUFFER *bp;
  708.   register LINE    *clp;
  709.   register int    clo;
  710.   register int    nline;
  711.   int        s;
  712.   char        bufn[NBUFN];
  713.   
  714.   /* Get buffer to use from user */
  715.   if (curbp->b_altb != NULL)
  716.     s=eread(insertbd, bufn, NBUFN, EFNEW|EFBUF, curbp->b_altb->b_bname);
  717.   else
  718.     s=eread(insertb, bufn, NBUFN, EFNEW|EFBUF);
  719.   if (s == ABORT) 
  720.     return (s);
  721.   if (s == FALSE && curbp->b_altb != NULL) 
  722.     bp = curbp->b_altb;
  723.   else 
  724.     if ((bp=bfind(bufn, FALSE)) == NULL) 
  725.       {
  726.         ttbeep();
  727.         ewprintf(nosuchbuffer);
  728.         return FALSE;
  729.       }
  730.   
  731.   if (bp==curbp) 
  732.     {
  733.       ewprintf(notself);
  734.       return FALSE;
  735.     }
  736.   
  737.   if (curbp->b_flag & BFVIEW)
  738.     {
  739.       ttbeep();
  740.       return FALSE;
  741.     }
  742.   if (filetimechanged(bp))
  743.     return(FALSE);
  744.   clearUndo(bp);
  745.  
  746.   /* insert the buffer 
  747.   */
  748.   nline = 0;
  749.   clp = lforw(bp->b_linep);
  750.   for(;;) 
  751.     {
  752.       for (clo = 0; clo < llength(clp); clo++)
  753.     if (linsert(1, lgetc(clp, clo)) == FALSE)
  754.       return FALSE;
  755.       if((clp = lforw(clp)) == bp->b_linep) 
  756.     break;
  757.       if (newline(FFRAND, 1) == FALSE) /* fake newline */
  758.     return FALSE;
  759.       nline++;
  760.     }
  761.  
  762.   /* Are these 2 strings worth it?
  763.   */
  764.   if (nline == 1) 
  765.     ewprintf("[Inserted 1 line]");
  766.   else    
  767.     ewprintf("[Inserted %d lines]", nline);
  768.   
  769.   clp = curwp->w_linep;            /* cosmetic adjustment */
  770.   if (curwp->w_dotp == clp)         /* for offscreen insert */
  771.     {
  772.       while (nline-- && lback(clp)!=curbp->b_linep)
  773.     clp = lback(clp);
  774.       curwp->w_linep = clp;        /* adjust framing.    */
  775.       curwp->w_flag |= WFHARD;
  776.     }
  777.   return (TRUE);
  778. }
  779.  
  780. /*
  781.  * Toggle the dirty bit on this buffer.
  782.  */
  783. /*ARGSUSED*/
  784. togglemodified(f, n)
  785. int f, n;
  786. {
  787.   BOOL hard = FALSE;
  788.   register LINE *lp;
  789.  
  790.   if (curbp->b_flag & BFVIEW)
  791.     {
  792.       ewprintf("Readonly buffer.");
  793.       return FALSE;
  794.     }
  795.  
  796.   /* sigh, this is costly...should have the highlight
  797.   * code check the modified bit on the buffer
  798.   * also before lighting the bits; that way you don't
  799.   * lose the info but the text doesn't light up
  800.   * all the time
  801.   */
  802.   lp = lforw(curbp->b_linep);
  803.   while (lp != curbp->b_linep)
  804.     {
  805.       if (lp->l_flag & LFCHANGE)
  806.         hard = TRUE;
  807.       changelineflag(lp, FALSE);
  808.       lp = lforw(lp);
  809.     }
  810.  
  811.   curbp->b_flag ^= BFCHG;
  812.  
  813.   if ((curbp->b_flag & BFCHG) == 0)
  814.     curbp->b_flag &= ~(BFINC | BFSAVED);
  815.   else
  816.     curbp->b_flag |= BFINC;
  817.  
  818.   if (hard)
  819.     upmodes(WFHARD);
  820.  
  821.   thisflag |= CFNEWC;
  822.   return TRUE;
  823. }
  824. togglereadonly(f, n)
  825. int f, n;
  826. {
  827.   if (curbp->b_modes[0] == name_mode(BlistStr))
  828.     {
  829.       ewprintf("Buffer List readonly!");
  830.       return (FALSE);
  831.     }
  832.  
  833.   curbp->b_flag ^= BFVIEW;
  834.  
  835.   if (curbp->b_flag & BFVIEW)
  836.     curbp->b_flag &= ~(BFCHG | BFINC | BFSAVED);
  837.  
  838.   thisflag |= CFNEWC;
  839.   return TRUE;
  840. }
  841.  
  842. /*
  843.  * Popbuf and set all windows to top of buffer.     Currently only used by
  844.  * help functions.
  845.  */
  846. popbuftop(bp)
  847. register BUFFER *bp;
  848. {
  849.   register EWINDOW *wp;
  850.   
  851.   bp->b_dotp = lforw(bp->b_linep);
  852.   bp->b_doto = 0;
  853.   if(bp->b_nwnd != 0) 
  854.     {
  855.       for(wp = wheadp; wp!=NULL; wp = wp->w_wndp)
  856.     if(wp->w_bufp == bp) 
  857.       {
  858.         wp->w_dotp = bp->b_dotp;
  859.         wp->w_doto = 0;
  860.         wp->w_flag |= WFHARD;
  861.       }
  862.     }
  863.   return popbuf(bp) != NULL;
  864. }
  865.  
  866.  
  867. /* Return name of active buffer, else
  868.  * punt. (JAM)
  869.  */
  870. char *GetCurrentBufferName()
  871. {
  872.   if (curbp)
  873.     return(curbp->b_fname);
  874.   else
  875.     return(Scratch);
  876. }
  877.  
  878. /* Grab a word under the cursor - kinda ughly (JAM)
  879. */
  880. int grabword(lnum, col, bname, len, bbuf)
  881. int *lnum;
  882. int *col; 
  883. char *bname; 
  884. int len; 
  885. BOOL bbuf;
  886. {
  887.  register int i, j;
  888.  char c;
  889.  register BUFFER *bp;
  890.  
  891.  bname[0] = '\0';
  892.  *lnum = -1;
  893.  
  894.  /* Find the word; if on space/tab, error and return
  895.  * else backup to word and then copy till work end
  896.  */
  897.  if (((c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' ') ||
  898.        ( c == '\t'))
  899.    {
  900.      ewprintf(bbuf ? notonname : notonword);
  901.      return(ABORT);
  902.    }
  903.  
  904.  /* backup to whitespace
  905.  */
  906.  for (i = curwp->w_doto; i >= 0; i--)
  907.   {
  908.     c = lgetc(curwp->w_dotp, i);
  909.     if ((c == ' ') || (c == '\t'))
  910.       {
  911.         i++;
  912.         break;
  913.       }
  914.   }
  915.  
  916.  /* get bname/word
  917.  */
  918.  *col = i;
  919.  for (j = 0; i < llength(curwp->w_dotp); i++, j++)
  920.    {
  921.      c = lgetc(curwp->w_dotp, i);
  922.      if ((j > len) || (c == ' ') || (c == '\t'))
  923.        break;
  924.      bname[j] = c;
  925.      bname[j+1] = '\0';
  926.    }
  927.  
  928.  /* Validate name (don't use blist from here - silly!)
  929.  */
  930.  if (bbuf)
  931.    {
  932.      if (strcmp(bname, blist) != 0)
  933.        for (bp = bheadp; bp != NULL; bp = bp->b_bufp)
  934.          if (strcmp(bp->b_bname, bname) == 0)
  935.  
  936.            /* found name, get line number & col
  937.            */
  938.            {
  939.              LINE *lp;
  940.       
  941.              lp = lforw(curwp->w_bufp->b_linep);  /* find the line number */
  942.              for (i = 1; lp != curwp->w_dotp;  i++)
  943.                lp = lforw(lp);
  944.              *lnum = i;
  945.              return (TRUE);
  946.            }
  947.       ewprintf(notonname);
  948.       return (ABORT); 
  949.     }
  950.  
  951.  /* just plain word
  952.  */
  953.  return (TRUE);
  954. }
  955. /* Activated via 's' in Buffer List window, if
  956. * on a valid buffer name (JAM)
  957. */
  958. int savethisbuffer(f, n)
  959. int f, n;
  960. {
  961.   int s, lnum, col;
  962.   BUFFER *bp;
  963.   char name[NBUFN];
  964.  
  965.   if ((s = grabword(&lnum, &col, name, NBUFN, TRUE)) == TRUE)
  966.     if (bp = bfind(name, FALSE))
  967.        if (s = buffsave(bp))
  968.           if (listbuffers(0, 1) == TRUE)
  969.             {
  970.               /* if worked, then curbp is buffer list
  971.               */
  972.               forwline(FFRAND, lnum -1);    /* in case at end */
  973.               curwp->w_doto = col;
  974.             }
  975.   return (s);
  976. }
  977. /* Activated via 'k' in Buffer List window, if
  978. * on a valid buffer name (JAM)
  979. */
  980. int zapbuffer(f, n)
  981. int f, n;
  982. {
  983.   char bname[NBUFN+1];
  984.   int s, lnum, col;
  985.  
  986.   if ((s = grabword(&lnum, &col, bname, NBUFN, TRUE) == TRUE))
  987.     {
  988.       AddString(bname); AddKchar(CCHR('J'));
  989.       if (killbuffer(0, 1) == TRUE)
  990.           if (listbuffers(0, 1) == TRUE)
  991.             {
  992.           curbp->b_dotp = curwp->w_dotp  = lforw(curbp->b_linep);
  993.               forwline(FFRAND, lnum - 1);           /* 1 less line now */
  994.               if (curwp->w_dotp == lforw(curwp->w_bufp->b_linep))
  995.                 forwline(FFRAND, lnum - 2);            /* wrap to end */
  996.               curbp->b_doto = curwp->w_doto = col;
  997.             }
  998.     }
  999.   return (s);
  1000. }
  1001. /* Activated via 'u' in Buffer List window, if
  1002. * on a valid buffer name (JAM)
  1003. */
  1004. int seebuffer(f, n)
  1005. int f, n;
  1006. {
  1007.   char bname[NBUFN+1];
  1008.   int s, lnum, col;
  1009.  
  1010.   if ((s = grabword(&lnum, &col, bname, NBUFN, TRUE) == TRUE))
  1011.     {
  1012.       AddString(bname); AddKchar(CCHR('J'));
  1013.       if (poptobuffer(0, 1) == TRUE)
  1014.         listbuffers(0, 1); 
  1015.     }
  1016.   return (s);
  1017. }
  1018. /* Update buffer-list buffer if visible; icky
  1019. * cause sometimes loses your place (JAM)
  1020. */
  1021. void update_blist()
  1022. {
  1023.   register EWINDOW *wp;
  1024.  
  1025.   for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
  1026.     if (strcmp(wp->w_bufp->b_bname, blist) == 0)
  1027.        listbuffers(0, 1);
  1028. }
  1029.  
  1030. int showbufferfile(f, n)
  1031. int f,n;
  1032. {
  1033.   ewprintf("Current buffer is on %s disk", curbp->b_fname);
  1034.   return(TRUE);
  1035. }